package co.fitstart.mobile.service.impl;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.persistence.GenericDaoSupport;

import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.course.round.CourseRoundGroup;
import co.fitstart.entity.course.round.OnlineRoundGroupStatus;
import co.fitstart.entity.order.Order;
import co.fitstart.entity.order.OrderInvestigateRecord;
import co.fitstart.entity.user.User;
import co.fitstart.entity.user.fit.Shape;
import co.fitstart.entity.user.fit.UserFit;
import co.fitstart.entity.user.investigation.FitInvestigation;
import co.fitstart.entity.user.investigation.HealthInvestigation;
import co.fitstart.entity.user.investigation.ParticipateInvestigation;
import co.fitstart.entity.user.investigation.ProfileInvestigation;
import co.fitstart.entity.user.profile.UserProfile;
import co.fitstart.entity.user.profile.UserRemark;
import co.fitstart.entity.user.profile.Wechat;
import co.fitstart.mobile.service.InvestigationService;

/**
 * 
 * @author mohanlan
 *
 */
@Service("investigationService")
public class InvestigationServiceImpl implements InvestigationService {
    
    public static final Logger logger = LoggerFactory.getLogger(InvestigationService.class);
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    /**
     * 
     * @param order
     * @param user
     * @return
     */
    private String generateZipName(OrderInvestigateRecord orderInvestigateRecord, User user) {
        String filename = org.apache.commons.lang3.StringUtils.replace(orderInvestigateRecord.getOrder().getProduct().getName(), " ", "-");
        
        String filePath = "[" + orderInvestigateRecord.getOrder().getOrderStatus().getDescription() + "-" + orderInvestigateRecord.getOrder().getPaymentStatus().getDescription() + "]" + filename + "_" + 
                user.getName() + "_" + user.getWechat().getCode() + "_" + 
                orderInvestigateRecord.getFitInvestigation().getHeight() + "_" + orderInvestigateRecord.getFitInvestigation().getWeight() + "_" + orderInvestigateRecord.getFitInvestigation().getBmiValue();
        
        return filePath;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#editProfile(co.fitstart.entity.user.User, co.fitstart.entity.user.investigation.ProfileInvestigation)
     */
    public void editProfile(User user, ProfileInvestigation profileInvestigation) {
        
        // Step1 save new profileInvestigation
        genericDaoSupport.save(profileInvestigation.bindUser(user).initialize());
        
        // Step2 sync user's userProfile and wechat
        Wechat wechat = user.getWechat() == null ? new Wechat() : user.getWechat();
        if(StringUtils.isNotEmpty(profileInvestigation.getQrcodePath())) {
            wechat.editQrcode(profileInvestigation.getQrcodePath());
        }
        wechat.editCode(profileInvestigation.getWechatCode());
        user.editWechat(wechat);
        
        UserProfile profile = user.getProfile() == null ? new UserProfile() :  user.getProfile();
        profile.editProfile(profileInvestigation.getCountry(), profileInvestigation.getProvince(), profileInvestigation.getRegion(), profileInvestigation.getDistrict(), profileInvestigation.getAddress());
        user.editProfile(profile);
        
        UserRemark remark = new UserRemark(profileInvestigation.getPosition(), profileInvestigation.getSalary(), profileInvestigation.getRemarks());
        user.editRemark(remark);
        
        genericDaoSupport.update(user.editMailbox(profileInvestigation.getMailbox()));
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#editProfile(co.fitstart.entity.user.User, co.fitstart.entity.order.OrderInvestigateRecord, co.fitstart.entity.user.investigation.ProfileInvestigation)
     */
    public void editProfile(User user, OrderInvestigateRecord orderInvestigateRecord, ProfileInvestigation profileInvestigation) {
        
        // Step1 save new profileInvestigation
        if(profileInvestigation.getId() == null) {
            genericDaoSupport.save(profileInvestigation.bindUser(user).initialize());
        } else {
            genericDaoSupport.update(profileInvestigation.bindUser(user).initialize());
        }
        
        // Step2 sync user's userProfile and wechat
        Wechat wechat = user.getWechat() == null ? new Wechat() : user.getWechat();
        if(StringUtils.isNotEmpty(profileInvestigation.getQrcodePath())) {
            wechat.editQrcode(profileInvestigation.getQrcodePath());
        }
        wechat.editCode(profileInvestigation.getWechatCode());
        user.editWechat(wechat);
        
        UserProfile profile = user.getProfile() == null ? new UserProfile() :  user.getProfile();
        profile.editProfile(profileInvestigation.getCountry(), profileInvestigation.getProvince(), profileInvestigation.getRegion(), profileInvestigation.getDistrict(), profileInvestigation.getAddress());
        user.editProfile(profile);
        
        UserRemark remark = new UserRemark(profileInvestigation.getPosition(), profileInvestigation.getSalary(), profileInvestigation.getRemarks());
        user.editRemark(remark);
        
        genericDaoSupport.update(user.editMailbox(profileInvestigation.getMailbox()));
        
        // Step3 update order investigation record
        genericDaoSupport.update(orderInvestigateRecord.profileInvestigation(profileInvestigation));
        
        // Step4 if investigate finished update courseRound and courseRoundGroup
        if(orderInvestigateRecord.isFinish()) {
            this.finishOrderInvestigate(orderInvestigateRecord, user);
        }
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#loadShape(java.lang.Long)
     */
    public Shape loadShape(Long shapeId) {
        return genericDaoSupport.load(Shape.class, shapeId);
    }


    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#editFit(co.fitstart.entity.user.User, co.fitstart.entity.user.investigation.FitInvestigation, co.fitstart.entity.user.fit.Shape)
     */
    public void editFit(User user, FitInvestigation fitInvestigation, Shape shape) {
        
        // Step1 save new profileInvestigation
        fitInvestigation.setShape(shape);
        genericDaoSupport.save(fitInvestigation.bindUser(user).initialize());
        
        // Step2 sync user's userFit
        UserFit fit = user.getUserFit() == null ? new UserFit() : user.getUserFit();
        fit.editShape(shape).editFit(fitInvestigation.getHeight(), fitInvestigation.getWeight(), fitInvestigation.getAge(), fitInvestigation.getGender());
        genericDaoSupport.update(user.editFit(fit));
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#editFit(co.fitstart.entity.user.User, co.fitstart.entity.order.OrderInvestigateRecord, co.fitstart.entity.user.investigation.FitInvestigation, co.fitstart.entity.user.fit.Shape)
     */
    public void editFit(User user, OrderInvestigateRecord orderInvestigateRecord, FitInvestigation fitInvestigation, Shape shape) {
        
        // Step1 sync user's userFit
        UserFit fit = user.getUserFit() == null ? new UserFit() : user.getUserFit();
        fit.editShape(shape).editFit(fitInvestigation.getHeight(), fitInvestigation.getWeight(), fitInvestigation.getAge(), fitInvestigation.getGender());
        genericDaoSupport.update(user.editFit(fit));
        
        // Step2 save new profileInvestigation
        fitInvestigation.setShape(shape);
        genericDaoSupport.saveOrUpdate(fitInvestigation.bindUser(user).initialize().editBmiValue(fit.getBmiValue()));
        
        // Step3 update orderInvestigateRecord
        genericDaoSupport.update(orderInvestigateRecord.fitInvestigation(fitInvestigation));
        
        // Step4 if investigate finished update courseRound and courseRoundGroup
        if(orderInvestigateRecord.isFinish()) {
            this.finishOrderInvestigate(orderInvestigateRecord, user);
        }
        
    }
    
    /* (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#editOfflineFit(co.fitstart.entity.user.User, co.fitstart.entity.order.OrderInvestigateRecord, co.fitstart.entity.user.investigation.FitInvestigation, co.fitstart.entity.user.fit.Shape, co.fitstart.entity.order.Order)
     */
    public void editOfflineFit(User user, OrderInvestigateRecord orderInvestigateRecord, FitInvestigation fitInvestigation, Shape shape, Order order) {
        
        // 1. update user's userFit
        UserFit userFit = user.getUserFit() == null ? new UserFit() : user.getUserFit();
        userFit.edit(shape, fitInvestigation).calculateBmi();
        genericDaoSupport.update(user.editFit(userFit));
        
        // 2. save new fitInvestigation
        fitInvestigation.setShape(shape);
        fitInvestigation.bindUser(user).initialize().editBmiValue(userFit.getBmiValue());
        genericDaoSupport.save(fitInvestigation);
        
        // 3. update orderInvestigation record
        genericDaoSupport.update(orderInvestigateRecord.fitInvestigation(fitInvestigation));
        
        // 4. update order invested status
        genericDaoSupport.update(order.investiged());
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#loadLastHealth(co.fitstart.entity.user.User)
     */
    @SuppressWarnings("unchecked")
    public HealthInvestigation loadLastHealth(User user) {
        String sentence = "FROM HealthInvestigation WHERE user = :user ORDER BY createTime DESC";
        List<HealthInvestigation> healthInvestigations = genericDaoSupport.searchForList(sentence, "user", user);
        return healthInvestigations.size() > 0 ? healthInvestigations.get(0) : null;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#editHealth(co.fitstart.entity.user.User, co.fitstart.entity.user.investigation.HealthInvestigation)
     */
    public void editHealth(User user, HealthInvestigation healthInvestigation) {
        // Step1 save new profileInvestigation
        genericDaoSupport.save(healthInvestigation.bindUser(user).initialize());
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#editHealth(co.fitstart.entity.user.User, co.fitstart.entity.order.OrderInvestigateRecord, co.fitstart.entity.user.investigation.HealthInvestigation)
     */
    public void editHealth(User user, OrderInvestigateRecord orderInvestigateRecord, HealthInvestigation healthInvestigation) {
        // Step1 save new profileInvestigation
        genericDaoSupport.saveOrUpdate(healthInvestigation.bindUser(user).initialize());
        
        // Step2 update orderInvestigateRecord
        genericDaoSupport.update(orderInvestigateRecord.healthInvestigation(healthInvestigation));
        
        // Step3 if investigate finished update courseRound and courseRoundGroup
        if(orderInvestigateRecord.isFinish()) {
            this.finishOrderInvestigate(orderInvestigateRecord, user);
        }
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#loadLastParticipate(co.fitstart.entity.user.User)
     */
    @SuppressWarnings("unchecked")
    public ParticipateInvestigation loadLastParticipate(User user) {
        String sentence = "FROM ParticipateInvestigation WHERE user = :user ORDER BY createTime DESC";
        List<ParticipateInvestigation> participateInvestigations = genericDaoSupport.searchForList(sentence, "user", user);
        return participateInvestigations.size() > 0 ? participateInvestigations.get(0) : null;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#editParticipate(co.fitstart.entity.user.User, co.fitstart.entity.user.investigation.ParticipateInvestigation)
     */
    public void editParticipate(User user, ParticipateInvestigation participateInvestigation) {

        // Step1 save new profileInvestigation
        genericDaoSupport.save(participateInvestigation.bindUser(user).initialize());
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.InvestigationService#editParticipate(co.fitstart.entity.user.User, co.fitstart.entity.order.OrderInvestigateRecord, co.fitstart.entity.user.investigation.ParticipateInvestigation)
     */
    public void editParticipate(User user, OrderInvestigateRecord orderInvestigateRecord, ParticipateInvestigation participateInvestigation) {
        
        // Step1 save new profileInvestigation
        genericDaoSupport.saveOrUpdate(participateInvestigation.bindUser(user).initialize());
        
        // Step2 update orderInvestigateRecord
        genericDaoSupport.update(orderInvestigateRecord.participateInvestigation(participateInvestigation));
        
        // Step3 if investigate finished update courseRound and courseRoundGroup
        if(orderInvestigateRecord.isFinish()) {
            this.finishOrderInvestigate(orderInvestigateRecord, user);
        }
        
    }
    
    /**
     * 
     * @param order
     * @param orderInvestigateRecord
     * @param user
     */
    @SuppressWarnings("unchecked")
    private void finishOrderInvestigate(OrderInvestigateRecord orderInvestigateRecord, User user) {
        
        CourseRound courseRound = genericDaoSupport.searchForObject("FROM CourseRound WHERE disabled = false AND order = :order", "order", orderInvestigateRecord.getOrder(), CourseRound.class);
        
        OnlineRoundGroupStatus status;
        List<CourseRoundGroup> courseRoundGroups = genericDaoSupport.searchForList("FROM CourseRoundGroup WHERE disabled = false AND courseRoundCode = :code", "code", courseRound.getCode());
        if(courseRoundGroups.isEmpty()) {
            status = OnlineRoundGroupStatus.GROUPING;
        } else {
            status = OnlineRoundGroupStatus.UNGROUPED;
        }
        
        String zipName = this.generateZipName(orderInvestigateRecord, user);
        genericDaoSupport.update(courseRound.editOnlineBasic(orderInvestigateRecord.getFitInvestigation().getBmiValue(), zipName, orderInvestigateRecord.isQrcodeStatus(), status));
    }
    
}
